package com.mlethe.library.camera.widget;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.SurfaceTexture;
import android.os.Build;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Size;
import android.view.TextureView;

import androidx.annotation.RequiresApi;

import com.mlethe.library.camera.Camera2Interface;

import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;

public class CameraTextureView extends TextureView implements TextureView.SurfaceTextureListener, Camera2Interface.PreviewCallback {

    private SurfaceViewListener mSurfaceViewListener;

    private int mRatioWidth = 0;
    private int mRatioHeight = 0;

    public CameraTextureView(Context context) {
        this(context, null);
    }

    public CameraTextureView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CameraTextureView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Camera2Interface.init((Activity) context);
        }
        setSurfaceTextureListener(this);
    }

    /**
     * 设置回调
     *
     * @param surfaceViewListener
     */
    public void setSurfaceViewListener(SurfaceViewListener surfaceViewListener) {
        this.mSurfaceViewListener = surfaceViewListener;
    }

    /**
     * A single preview frame will be returned to the handler supplied. The data will arrive as byte[]
     * in the message.obj field, with width and height encoded as message.arg1 and message.arg2,
     * respectively.
     *
     * @param handler The handler to send the message to.
     * @param message The what field of the message to be sent.
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void requestPreviewFrame(Handler handler, int message) {
        Camera2Interface.getInstance().requestPreviewFrame(handler, message);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (0 == mRatioWidth || 0 == mRatioHeight) {
            setMeasuredDimension(width, height);
        } else {
            Configuration configuration = getResources().getConfiguration();
            int orientation = configuration.orientation;
            if (orientation == ORIENTATION_LANDSCAPE) {
                // 横屏
                setMeasuredDimension(width, width * mRatioHeight /mRatioWidth);
            } else {
                setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
            }
        }
    }

    /**
     * 在SurfaceTexture准备使用时调用
     *
     * @param surface
     * @param width
     * @param height
     */
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Camera2Interface instance = Camera2Interface.getInstance();
            instance.setPreviewCallback(this)
                    .openCamera(surface);
            Size size = instance.getPreviewSize();
            if (size != null) {
                Configuration configuration = getResources().getConfiguration();
                int orientation = configuration.orientation;
                if (orientation == ORIENTATION_LANDSCAPE) {
                    mRatioWidth = size.getWidth();
                    mRatioHeight = size.getHeight();
                } else {
                    mRatioWidth = size.getHeight();
                    mRatioHeight = size.getWidth();
                }
                requestLayout();
            }
        }
    }

    /**
     * 当SurfaceTexture缓冲区大小更改时调用。
     *
     * @param surface
     * @param width
     * @param height
     */
    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
    }

    /**
     * 当指定SurfaceTexture即将被销毁时调用。如果返回true，则调用此方法后，表面纹理中不会发生渲染。如果返回false，则客户端需要调用release()。大多数应用程序应该返回true
     *
     * @param surface
     * @return
     */
    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Camera2Interface.getInstance().closeCamera();
        }
        return true;
    }

    /**
     * 当指定SurfaceTexture的更新时调用updateTexImage()。
     *
     * @param surface
     */
    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        if (visibility == VISIBLE) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Camera2Interface.getInstance().startPreview();
            }
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Camera2Interface.getInstance().stopPreview();
            }
        }
    }

    @Override
    public void onCameraBrightnessChanged(boolean isDark) {
        if (mSurfaceViewListener != null) {
            mSurfaceViewListener.onCameraBrightnessChanged(isDark);
        }
    }

    @Override
    public void onOpenCameraError() {
        if (mSurfaceViewListener != null) {
            mSurfaceViewListener.onOpenCameraError();
        }
    }

    public interface SurfaceViewListener {
        /**
         * 摄像头环境亮度发生变化
         *
         * @param isDark 是否变暗
         */
        void onCameraBrightnessChanged(boolean isDark);

        /**
         * 处理打开相机出错
         */
        void onOpenCameraError();
    }

}
